package com.titan.core.utils.file;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.Charsets;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.StringBuilderWriter;

import com.titan.core.utils.comm.SocketUtils;

/**
 * @author 周成功
 * @email 86898837@qq.com
 * @date 2020年02月20日
 */
public class FileUtils {
    public static final String LINE_SEPARATOR;
    static {
        // avoid security issues
        final StringBuilderWriter buf = new StringBuilderWriter(4);
        final PrintWriter out = new PrintWriter(buf);
        out.println();
        LINE_SEPARATOR = buf.toString();
        out.close();
    }
    
    
    public static List<String> toLines(File file, String encoding) throws Exception {
        if( file==null || (file.exists()==false) || (file.isFile()==false) ) {
            return null;
        }
        InputStream input = null;
        try {
            input = new FileInputStream(file);
            return toLines(input, encoding);
        } finally {
            SocketUtils.closeQuietly(input);
        }
    }
    public static List<String> toLines(InputStream input, String encoding) throws Exception {
        if( input==null ) {
            return null;
        }
        BufferedReader buffer = null;
        try {
            InputStreamReader reader = new InputStreamReader(input, Charsets.toCharset(encoding));
            buffer = new BufferedReader(reader);
            return toLines(buffer);
        } finally {
            SocketUtils.closeQuietly(buffer);
        }
    }
    public static List<String> toLines(BufferedReader reader) throws Exception {
        if( reader==null ) {
            return null;
        }
        final List<String> list = new ArrayList<String>();
        String line = reader.readLine();
        while (line != null) {
            list.add(line);
            line = reader.readLine();
        }
        return list;
    }
    
    
    public static boolean create(String name) throws Exception {
        File f = new File(name);
        if (f.exists()) {
            return true;
        }
        String path = name;
        int pos = name.lastIndexOf(File.separator);
        if (pos != -1) {
            path = name.substring(0, pos);
        }
        File filepath = new File(path);
        if (!filepath.exists()) {
            return filepath.mkdirs();
        }
        File file = new File(name);
        try {
            file.createNewFile();
        } catch (IOException e) {
            throw new Exception("create file [" + name + "] failure", e);
        }
        return true;
    }
    public static boolean createFile(File file) throws IOException {
        File dir = file.getParentFile();
        if( dir!=null && dir.exists()==false ) {
            dir.mkdirs();
        }
        if(file.exists()==false) {
            return file.createNewFile();
        }
        return true;
    }    
    
    public static File create(final String filePath, final String fileName) throws IOException {
        File path = new File(filePath);
        return create(path, fileName);
    }
    public static File create(final File filePath, final String fileName) throws IOException {
        if (!filePath.exists()) {
            filePath.mkdirs();
        }
//        String filePathFull = filePath.endsWith(File.separator) ? filePath : (filePath + File.separator);
        File file = new File(filePath, fileName);
        if (!file.exists()) {
            file.createNewFile();
        }
        return file;
    }    
    
    public static File write(final String filePath, final String fileName, final String data, final String encoding, final boolean append) throws IOException {
        File file = create(filePath, fileName);
        return write(file, data, encoding, append);
    }
    public static File write(final File file, final String data, final String encoding, final boolean append) throws IOException {
        OutputStream output = null;
        OutputStreamWriter writer = null;
        BufferedWriter buffer = null;
        try {
            output = new FileOutputStream(file, append);
            writer = new OutputStreamWriter(output, encoding);
            buffer = new BufferedWriter(writer);
            buffer.write(data);
            buffer.flush();
            return file;
        } catch(FileNotFoundException ex) {
            FileUtils.createFile(file);
            return write(file, data, encoding, append);
        } finally {
            SocketUtils.closeQuietly(buffer);
            SocketUtils.closeQuietly(writer);
            SocketUtils.closeQuietly(output);
        }
    }    
    public static File write(final File file, final List<String> lines, final String encoding, final boolean append) throws IOException {
        if( file==null || lines==null || lines.size()==0 ) {
            return file;
        }
        if(file.exists()==false) {
            FileUtils.createFile(file);
        }
        
        OutputStream output = null;
        OutputStreamWriter writer = null;
        BufferedWriter buffer = null;
        try {
            output = new FileOutputStream(file, append);
            writer = new OutputStreamWriter(output, encoding);
            buffer = new BufferedWriter(writer);
            
            for (final Object line : lines) {
                if (line != null) {
                    buffer.write(line.toString());
                }
                buffer.write(LINE_SEPARATOR);
            }            
            
            buffer.flush();
            return file;
        } catch(FileNotFoundException ex) {
            FileUtils.createFile(file);
            return write(file, lines, encoding, append);
        } finally {
            SocketUtils.closeQuietly(buffer);
            SocketUtils.closeQuietly(writer);
            SocketUtils.closeQuietly(output);
        }
    }
    public static File write(final File file, final byte[] data, final boolean append) throws IOException {
        OutputStream output = null;
        try {
            output = new FileOutputStream(file, append);
            IOUtils.write(data, output);
            output.flush();
            return file;
        } finally {
            SocketUtils.closeQuietly(output);
        }
    }    
    
}
